@@ -134,6 +134,7 @@ urlpatterns += [ |
||
| 134 | 134 |
# 系统相关 |
| 135 | 135 |
urlpatterns += [ |
| 136 | 136 |
url(r'^op/upgrade$', op_views.upgrade_api, name='upgrade_api'), # APP 升级 |
| 137 |
+ url(r'^op/patch$', op_views.patch_api, name='patch_api'), # APP 补丁 |
|
| 137 | 138 |
url(r'^op/online$', op_views.online_api, name='online_api'), # 是否上线 |
| 138 | 139 |
url(r'^op/splash$', op_views.splash_api, name='splash_api'), # 启动页面 |
| 139 | 140 |
url(r'^op/feedback$', op_views.feedback_api, name='feedback_api'), # 用户反馈 |
@@ -5,10 +5,12 @@ from django.contrib import admin |
||
| 5 | 5 |
from django.template.loader import render_to_string |
| 6 | 6 |
from pysnippets.strsnippets import strip |
| 7 | 7 |
|
| 8 |
-from operation.models import APPSettingsInfo, FeedbackInfo, GuestEntranceControlInfo, LatestAppInfo, SplashInfo |
|
| 8 |
+from operation.models import (APPSettingsInfo, FeedbackInfo, GuestEntranceControlInfo, LatestAppInfo, PatchInfo, |
|
| 9 |
+ SplashInfo) |
|
| 9 | 10 |
from utils.disk_utils import write_to_disk |
| 10 | 11 |
from utils.redis.rapp import set_latest_app |
| 11 | 12 |
from utils.redis.rguest import delete_guest_entrance_control, set_guest_entrance_control |
| 13 |
+from utils.redis.rpatch import del_app_patch_info, set_app_patch_info |
|
| 12 | 14 |
from utils.redis.rsettings import del_app_settings_info, set_app_settings_info |
| 13 | 15 |
|
| 14 | 16 |
|
@@ -68,6 +70,24 @@ class LatestAppInfoAdmin(admin.ModelAdmin): |
||
| 68 | 70 |
set_latest_app(obj.src) |
| 69 | 71 |
|
| 70 | 72 |
|
| 73 |
+class PatchInfoAdmin(admin.ModelAdmin): |
|
| 74 |
+ list_display = ('platform', 'version', 'patch', 'src', 'status', 'created_at', 'updated_at')
|
|
| 75 |
+ list_filter = ('platform', 'src', 'status')
|
|
| 76 |
+ |
|
| 77 |
+ def save_model(self, request, obj, form, change): |
|
| 78 |
+ obj.version = strip(obj.version) |
|
| 79 |
+ obj.save() |
|
| 80 |
+ |
|
| 81 |
+ # 设置 APP 补丁信息 |
|
| 82 |
+ set_app_patch_info(obj) |
|
| 83 |
+ |
|
| 84 |
+ def delete_model(self, request, obj): |
|
| 85 |
+ obj.delete() |
|
| 86 |
+ |
|
| 87 |
+ # 删除 APP 补丁信息 |
|
| 88 |
+ del_app_patch_info(obj) |
|
| 89 |
+ |
|
| 90 |
+ |
|
| 71 | 91 |
class APPSettingsInfoAdmin(admin.ModelAdmin): |
| 72 | 92 |
list_display = ('platform', 'channel', 'version', 'online', 'status', 'created_at', 'updated_at')
|
| 73 | 93 |
list_filter = ('platform', 'online', 'status')
|
@@ -118,6 +138,7 @@ class GuestEntranceControlInfoAdmin(admin.ModelAdmin): |
||
| 118 | 138 |
|
| 119 | 139 |
|
| 120 | 140 |
admin.site.register(LatestAppInfo, LatestAppInfoAdmin) |
| 141 |
+admin.site.register(PatchInfo, PatchInfoAdmin) |
|
| 121 | 142 |
admin.site.register(APPSettingsInfo, APPSettingsInfoAdmin) |
| 122 | 143 |
admin.site.register(SplashInfo, SplashInfoAdmin) |
| 123 | 144 |
admin.site.register(FeedbackInfo, FeedbackInfoAdmin) |
@@ -0,0 +1,37 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.db import models, migrations |
|
| 5 |
+import operation.models |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class Migration(migrations.Migration): |
|
| 9 |
+ |
|
| 10 |
+ dependencies = [ |
|
| 11 |
+ ('operation', '0009_auto_20161220_1354'),
|
|
| 12 |
+ ] |
|
| 13 |
+ |
|
| 14 |
+ operations = [ |
|
| 15 |
+ migrations.CreateModel( |
|
| 16 |
+ name='PatchInfo', |
|
| 17 |
+ fields=[ |
|
| 18 |
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
| 19 |
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
| 20 |
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
| 21 |
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
| 22 |
+ ('platform', models.IntegerField(default=0, help_text='\u652f\u6301\u5e73\u53f0', db_index=True, verbose_name='plat', choices=[(0, '\u5168\u5e73\u53f0'), (1, 'Android'), (2, 'iOS')])),
|
|
| 23 |
+ ('version', models.CharField(help_text='\u7248\u672c\uff081.0.0\uff09', max_length=255, null=True, verbose_name='version', blank=True)),
|
|
| 24 |
+ ('patch', models.FileField(help_text='\u8865\u4e01', upload_to=operation.models.upload_path, null=True, verbose_name='patch', blank=True)),
|
|
| 25 |
+ ('src', models.IntegerField(default=0, help_text='\u6700\u65b0\u7248\u6765\u6e90', db_index=True, verbose_name='src', choices=[(0, '\u62cd\u7231\u7528\u6237\u7aef'), (1, '\u62cd\u7231\u6444\u5f71\u5e08\u7aef'), (2, '\u62cd\u7231\u5bfc\u6e38\u7aef')])),
|
|
| 26 |
+ ], |
|
| 27 |
+ options={
|
|
| 28 |
+ 'verbose_name': 'patchinfo', |
|
| 29 |
+ 'verbose_name_plural': 'patchinfo', |
|
| 30 |
+ }, |
|
| 31 |
+ ), |
|
| 32 |
+ migrations.AlterField( |
|
| 33 |
+ model_name='appsettingsinfo', |
|
| 34 |
+ name='version', |
|
| 35 |
+ field=models.CharField(help_text='\u7248\u672c\uff081.0.0\uff09', max_length=255, null=True, verbose_name='version', blank=True), |
|
| 36 |
+ ), |
|
| 37 |
+ ] |
@@ -63,9 +63,43 @@ class LatestAppInfo(CreateUpdateMixin): |
||
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 | 65 |
|
| 66 |
+class PatchInfo(CreateUpdateMixin, PlatformMixin): |
|
| 67 |
+ PAIAI_USER = 0 |
|
| 68 |
+ PAIAI_LENSMAN = 1 |
|
| 69 |
+ PAIAI_TOURGUIDE = 2 |
|
| 70 |
+ |
|
| 71 |
+ SRC = ( |
|
| 72 |
+ (PAIAI_USER, u'拍爱用户端'), |
|
| 73 |
+ (PAIAI_LENSMAN, u'拍爱摄影师端'), |
|
| 74 |
+ (PAIAI_TOURGUIDE, u'拍爱导游端'), |
|
| 75 |
+ ) |
|
| 76 |
+ |
|
| 77 |
+ version = models.CharField(_(u'version'), max_length=255, blank=True, null=True, help_text=u'版本(1.0.0)') |
|
| 78 |
+ patch = models.FileField(_(u'patch'), upload_to=upload_path, blank=True, null=True, help_text=u'补丁') |
|
| 79 |
+ |
|
| 80 |
+ src = models.IntegerField(_(u'src'), choices=SRC, default=PAIAI_USER, help_text=u'最新版来源', db_index=True) |
|
| 81 |
+ |
|
| 82 |
+ class Meta: |
|
| 83 |
+ verbose_name = _('patchinfo')
|
|
| 84 |
+ verbose_name_plural = _('patchinfo')
|
|
| 85 |
+ |
|
| 86 |
+ def __unicode__(self): |
|
| 87 |
+ return u'{0.pk}'.format(self)
|
|
| 88 |
+ |
|
| 89 |
+ @property |
|
| 90 |
+ def patch_url(self): |
|
| 91 |
+ return u'{}{}'.format(settings.DOMAIN, self.patch and self.patch.url)
|
|
| 92 |
+ |
|
| 93 |
+ @property |
|
| 94 |
+ def data(self): |
|
| 95 |
+ return {
|
|
| 96 |
+ 'patch_url': self.patch_url, |
|
| 97 |
+ } |
|
| 98 |
+ |
|
| 99 |
+ |
|
| 66 | 100 |
class APPSettingsInfo(CreateUpdateMixin, PlatformMixin): |
| 67 | 101 |
channel = models.CharField(_(u'channel'), max_length=255, blank=True, null=True, help_text=u'渠道') |
| 68 |
- version = models.CharField(_(u'version'), max_length=255, blank=True, null=True, help_text=u'版本') |
|
| 102 |
+ version = models.CharField(_(u'version'), max_length=255, blank=True, null=True, help_text=u'版本(1.0.0)') |
|
| 69 | 103 |
|
| 70 | 104 |
online = models.BooleanField(_(u'online'), default=True, help_text=u'是否上线') |
| 71 | 105 |
|
@@ -9,6 +9,7 @@ from operation.models import FeedbackInfo, LatestAppInfo, SplashInfo |
||
| 9 | 9 |
from utils.error.errno_utils import UserStatusCode |
| 10 | 10 |
from utils.error.response_utils import response |
| 11 | 11 |
from utils.redis.rapp import get_latest_app |
| 12 |
+from utils.redis.rpatch import get_app_patch_info |
|
| 12 | 13 |
from utils.redis.rsettings import get_app_settings_info |
| 13 | 14 |
|
| 14 | 15 |
|
@@ -37,6 +38,21 @@ def upgrade_api(request): |
||
| 37 | 38 |
}) |
| 38 | 39 |
|
| 39 | 40 |
|
| 41 |
+@logit |
|
| 42 |
+def patch_api(request): |
|
| 43 |
+ """ APP 补丁 """ |
|
| 44 |
+ platform = request.REQUEST.get('platform', '')
|
|
| 45 |
+ version = request.REQUEST.get('version', '')
|
|
| 46 |
+ src = int(request.POST.get('src', 0))
|
|
| 47 |
+ |
|
| 48 |
+ patch_info = get_app_patch_info(platform, version, src) |
|
| 49 |
+ |
|
| 50 |
+ return response(200, 'Get Patch Info Success', u'获取补丁信息成功', {
|
|
| 51 |
+ 'patch_url': patch_info.get('patch_url', ''),
|
|
| 52 |
+ }) |
|
| 53 |
+ |
|
| 54 |
+ |
|
| 55 |
+@logit |
|
| 40 | 56 |
def online_api(request): |
| 41 | 57 |
""" 是否上线 """ |
| 42 | 58 |
platform = request.REQUEST.get('platform', '')
|
@@ -32,7 +32,9 @@ class PlatformMixin(models.Model): |
||
| 32 | 32 |
abstract = True |
| 33 | 33 |
|
| 34 | 34 |
Platforms = {
|
| 35 |
+ 'ios': IOS, |
|
| 35 | 36 |
'iOS': IOS, |
| 37 |
+ 'adr': ADR, |
|
| 36 | 38 |
'android': ADR, |
| 37 | 39 |
'Android': ADR, |
| 38 | 40 |
} |
@@ -64,3 +64,4 @@ GUEST_ENTRANCE_CONTROL_INFO = 'guest:entrance:control:info' # STRING,游客 |
||
| 64 | 64 |
# APP 相关 |
| 65 | 65 |
LATEST_APP_INFO = 'latest:app:info:%s' # STRING,最新 APP 信息,src |
| 66 | 66 |
APP_SETTINGS_INFO = 'app:settings:info:%s:%s:%s' # STRING,APP 设置信息,platform、channel、version |
| 67 |
+APP_PATCH_INFO = 'app:patch:info:%s:%s:%s' # STRING,APP 补丁信息,platform、version、src |
@@ -0,0 +1,23 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+import json |
|
| 4 |
+ |
|
| 5 |
+from pai2.basemodels import PlatformMixin |
|
| 6 |
+from utils.redis.connect import r |
|
| 7 |
+from utils.redis.rkeys import APP_PATCH_INFO |
|
| 8 |
+ |
|
| 9 |
+ |
|
| 10 |
+def set_app_patch_info(apppatch): |
|
| 11 |
+ """ 设置 APP 补丁信息 """ |
|
| 12 |
+ r.set(APP_PATCH_INFO % (apppatch.platform, apppatch.version, apppatch.src), json.dumps(apppatch.data)) |
|
| 13 |
+ |
|
| 14 |
+ |
|
| 15 |
+def del_app_patch_info(apppatch): |
|
| 16 |
+ """ 删除 APP 补丁信息 """ |
|
| 17 |
+ r.delete(APP_PATCH_INFO % (apppatch.platform, apppatch.version, apppatch.src)) |
|
| 18 |
+ |
|
| 19 |
+ |
|
| 20 |
+def get_app_patch_info(platform, version, src): |
|
| 21 |
+ """ 获取 APP 补丁信息 """ |
|
| 22 |
+ platform = platform if isinstance(platform, int) else PlatformMixin.Platforms.get(platform) |
|
| 23 |
+ return json.loads(r.get(APP_PATCH_INFO % (platform, version, src)) or '{}')
|